home *** CD-ROM | disk | FTP | other *** search
- Subject: v15i019: Tools to create and unpack shell archives, Part02/03
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Rich Salz <rsalz@bbn.com>
- Posting-number: Volume 15, Issue 19
- Archive-name: cshar/part02
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 2 (of 3)."
- # Contents: dir.amiga findsrc.c makekit.c shar.c unshar.c
- # Wrapped by rsalz@fig.bbn.com on Fri May 27 14:15:08 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'dir.amiga' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dir.amiga'\"
- else
- echo shar: Extracting \"'dir.amiga'\" \(6596 characters\)
- sed "s/^X//" >'dir.amiga' <<'END_OF_FILE'
- X
- X[ I have not tried this at all. --r$ ]
- X
- Return-Path: mwm@violet.Berkeley.EDU
- Received: from violet.berkeley.edu (violet.berkeley.edu.ARPA) by PINEAPPLE.BBN.COM (4.12/4.7) id AA28194; Tue, 14 Jul 87 00:52:17 edt
- Received: from localhost.ARPA
- X by violet.berkeley.edu (5.54 (CFC 4.22.3)/1.16.15)
- X id AA16462; Mon, 13 Jul 87 21:54:26 PDT
- Message-Id: <8707140454.AA16462@violet.berkeley.edu>
- To: Richard Salz <rsalz@pineapple.bbn.com>
- Subject: Re: Amiga version of the dir library...
- Ultrix: Just say No!
- In-Reply-To: Your message of Wed, 08 Jul 87 21:19:51 -0400
- Date: Mon, 13 Jul 87 21:54:25 PDT
- XFrom: Mike (My watch has windows) Meyer <mwm@violet.Berkeley.EDU>
- X
- Here's what I did. This is built to reflect the 4BSD manual pages, not
- the SysV/dpANS manual pages.
- X
- I now know how to get the telldir/seekdir pair to work correctly with
- multiple tell()s, but don't have much motivation to do so. If someone
- out there does it, or is interested in doing it, I'd be interested in
- the results or willing to help.
- X
- XFinal note: as with many micros, there's more than one C compiler.
- This was written for the Lattice compiler, and uses features known
- not to exist in other Amiga compilers. Fixing it should be trivial.
- X
- Oh, yeah - sorry for the delay in getting these two you.
- X
- X <mike
- X
- X#! /bin/sh
- X# This is a shell archive, meaning:
- X# 1. Remove everything above the #! /bin/sh line.
- X# 2. Save the resulting text in a file.
- X# 3. Execute the file with /bin/sh (not csh) to create:
- X# dir.h
- X# ndir.c
- X# By: Mike (My watch has windows) Meyer (Missionaria Phonibalonica)
- export PATH; PATH=/bin:/usr/bin:$PATH
- echo shar: "extracting 'dir.h'" '(1708 characters)'
- if test -f 'dir.h'
- then
- X echo shar: "will not over-write existing file 'dir.h'"
- else
- sed 's/^X//' << \SHAR_EOF > 'dir.h'
- XX#ifndef DIR_H
- XX#define DIR_H
- XX
- XX#ifndef EXEC_TYPES_H
- XX#include "exec/types.h"
- XX#endif
- XX
- XX#ifndef LIBRARIES_DOS_H
- XX#include "libraries/dos.h"
- XX#endif
- XX
- XX#ifndef LIBRARIES_DOSEXTENS_H
- XX#include "libraries/dosextens.h"
- XX#endif
- XX/*
- XX * MAXNAMELEN is the maximum length a file name can be. The direct structure
- XX * is lifted form 4BSD, and has not been changed so that code which uses
- XX * it will be compatable with 4BSD code. d_ino and d_reclen are unused,
- XX * and will probably be set to some non-zero value.
- XX */
- XX#define MAXNAMLEN 31 /* AmigaDOS file max length */
- XX
- XXstruct direct {
- XX ULONG d_ino ; /* unused - there for compatability */
- XX USHORT d_reclen ; /* ditto */
- XX USHORT d_namlen ; /* length of string in d_name */
- XX char d_name[MAXNAMLEN + 1] ; /* name must be no longer than this */
- XX};
- XX/*
- XX * The DIRSIZ macro gives the minimum record length which will hold
- XX * the directory entry. This requires the amount of space in struct direct
- XX * without the d_name field, plus enough space for the name with a terminating
- XX * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
- XX */
- XX
- XX#undef DIRSIZ
- XX#define DIRSIZ(dp) \
- XX ((sizeof(struct direct) - (MAXNAMLEN+1)) + (((dp) -> d_namlen+1 + 3) &~ 3))
- XX/*
- XX * The DIR structure holds the things that AmigaDOS needs to know about
- XX * a file to keep track of where it is and what it's doing.
- XX */
- XX
- XXtypedef struct {
- XX struct FileInfoBlock d_info , /* Default info block */
- XX d_seek ; /* Info block for seeks */
- XX struct FileLock *d_lock ; /* Lock on directory */
- XX } DIR ;
- XX
- XXextern DIR *opendir(char *) ;
- XXextern struct direct *readdir(DIR *) ;
- XXextern long telldir(DIR *) ;
- XXextern void seekdir(DIR *, long) ;
- XXextern void rewinddir(DIR *) ;
- XXextern void closedir(DIR *) ;
- XX#endif DIR_H
- SHAR_EOF
- if test 1708 -ne "`wc -c < 'dir.h'`"
- then
- X echo shar: "error transmitting 'dir.h'" '(should have been 1708 characters)'
- fi
- fi
- echo shar: "extracting 'ndir.c'" '(2486 characters)'
- if test -f 'ndir.c'
- then
- X echo shar: "will not over-write existing file 'ndir.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'ndir.c'
- XX/*
- XX * ndir - routines to simulate the 4BSD new directory code for AmigaDOS.
- XX */
- XX#include <dir.h>
- XX
- XXDIR *
- XXopendir(dirname) char *dirname; {
- XX register DIR *my_dir, *AllocMem(int, int) ;
- XX struct FileLock *Lock(char *, int), *CurrentDir(struct FileLock *) ;
- XX
- XX if ((my_dir = AllocMem(sizeof(DIR), 0)) == NULL) return NULL ;
- XX
- XX
- XX if (((my_dir -> d_lock = Lock(dirname, ACCESS_READ)) == NULL)
- XX /* If we can't examine it */
- XX || !Examine(my_dir -> d_lock, &(my_dir -> d_info))
- XX /* Or it's not a directory */
- XX || (my_dir -> d_info . fib_DirEntryType < 0)) {
- XX FreeMem(my_dir, sizeof(DIR)) ;
- XX return NULL ;
- XX }
- XX return my_dir ;
- XX }
- XX
- XXstruct direct *
- XXreaddir(my_dir) DIR *my_dir; {
- XX static struct direct result ;
- XX
- XX if (!ExNext(my_dir -> d_lock, &(my_dir -> d_info))) return NULL ;
- XX
- XX result . d_reclen = result . d_ino = 1 ; /* Not NULL! */
- XX (void) strcpy(result . d_name, my_dir -> d_info . fib_FileName) ;
- XX result . d_namlen = strlen(result . d_name) ;
- XX return &result ;
- XX }
- XX
- XXvoid
- XXclosedir(my_dir) DIR *my_dir; {
- XX
- XX UnLock(my_dir -> d_lock) ;
- XX FreeMem(my_dir, sizeof(DIR)) ;
- XX }
- XX/*
- XX * telldir and seekdir don't work quite right. The problem is that you have
- XX * to save more than a long's worth of stuff to indicate position, and it's
- XX * socially unacceptable to alloc stuff that you don't free later under
- XX * AmigaDOS. So we fake it - you get one level of seek, and dat's all.
- XX * As of now, these things are untested.
- XX */
- XX#define DIR_SEEK_RETURN ((long) 1) /* Not 0! */
- XXlong
- XXtelldir(my_dir) DIR *my_dir; {
- XX
- XX my_dir -> d_seek = my_dir -> d_info ;
- XX return (long) DIR_SEEK_RETURN ;
- XX }
- XX
- XXvoid
- XXseekdir(my_dir, where) DIR *my_dir; long where; {
- XX
- XX if (where == DIR_SEEK_RETURN)
- XX my_dir -> d_info = my_dir -> d_seek ;
- XX else /* Makes the next readdir fail */
- XX setmem((char *) my_dir, sizeof(DIR), 0) ;
- XX }
- XX
- XXvoid
- XXrewinddir(my_dir) DIR *my_dir; {
- XX
- XX if (!Examine(my_dir -> d_lock, &(my_dir -> d_info)))
- XX setmem((char *) my_dir, sizeof(DIR), 0) ;
- XX }
- XX#ifdef TEST
- XX/*
- XX * Simple code to list the files in the argument directory,
- XX * lifted straight from the man page.
- XX */
- XX#include <stdio.h>
- XXvoid
- XXmain(argc, argv) int argc; char **argv; {
- XX register DIR *dirp ;
- XX register struct direct *dp ;
- XX register char *name ;
- XX
- XX if (argc < 2) name = "" ;
- XX else name = argv[1] ;
- XX
- XX if ((dirp = opendir(name)) == NULL) {
- XX fprintf(stderr, "Bogus! Can't opendir %s\n", name) ;
- XX exit(1) ;
- XX }
- XX
- XX for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp))
- XX printf("%s ", dp -> d_name) ;
- XX closedir(dirp);
- XX putchar('\n') ;
- XX }
- XX#endif TEST
- XX
- SHAR_EOF
- if test 2486 -ne "`wc -c < 'ndir.c'`"
- then
- X echo shar: "error transmitting 'ndir.c'" '(should have been 2486 characters)'
- fi
- fi
- exit 0
- X# End of shell archive
- END_OF_FILE
- if test 6596 -ne `wc -c <'dir.amiga'`; then
- echo shar: \"'dir.amiga'\" unpacked with wrong size!
- fi
- # end of 'dir.amiga'
- fi
- if test -f 'findsrc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'findsrc.c'\"
- else
- echo shar: Extracting \"'findsrc.c'\" \(7195 characters\)
- sed "s/^X//" >'findsrc.c' <<'END_OF_FILE'
- X/*
- X** FINDSRC
- X** Walk directories, trying to find source files.
- X*/
- X#include "shar.h"
- X#ifdef RCSID
- static char RCS[] =
- X "$Header: findsrc.c,v 2.0 88/05/27 13:26:05 rsalz Exp $";
- X#endif /* RCSID */
- X
- X
- X/*
- X** Global variables.
- X*/
- int DoDOTFILES; /* Do .newsrc and friends? */
- int DoRCS; /* Do RCS and SCCS files? */
- int Default; /* Default answer from user */
- int Verbose; /* List rejected files, too? */
- char *Dname; /* Filename of directory list */
- char *Fname; /* Filename of file list */
- XFILE *Dfile; /* List of directories found */
- XFILE *Ffile; /* List of files found */
- XFILE *DEVTTY; /* The tty, if in filter mode */
- X
- X
- X/*
- X** Signal handler. Clean up and die.
- X*/
- static sigret_t
- Catch(s)
- X int s;
- X{
- X int e;
- X
- X e = errno;
- X if (Dname)
- X (void)unlink(Dname);
- X if (Fname)
- X (void)unlink(Fname);
- X Fprintf(stderr, "Got signal %d, %s.\n", s, Ermsg(e));
- X exit(1);
- X}
- X
- X
- X/*
- X** Given a filename, apply heuristics to see if we want it.
- X*/
- static int
- Wanted(Name)
- X REGISTER char *Name;
- X{
- X REGISTER FILE *F;
- X REGISTER char *s;
- X REGISTER char *p;
- X REGISTER char *d;
- X char buff[BUFSIZ];
- X
- X /* Get down to brass tacks. */
- X s = (p = RDX(Name, '/')) ? p + 1 : Name;
- X
- X /* Only do directories other than . and .. and regular files. */
- X if ((Ftype(Name) != F_DIR && Ftype(Name) != F_FILE)
- X || EQ(s, ".") || EQ(s, ".."))
- X return(FALSE);
- X
- X /* Common cruft we never want. */
- X if (EQ(s, "foo") || EQ(s, "core") || EQ(s, "tags") || EQ(s, "lint"))
- X return(FALSE);
- X
- X /* Disregard stuff with bogus suffixes. */
- X d = RDX(s, '.');
- X if ((p = d)
- X && (EQ(++p, "out") || EQ(p, "orig") || EQ(p, "rej") || EQ(p, "BAK")
- X || EQ(p, "CKP") || EQ(p, "old") || EQ(p, "o") || EQ(p, "EXE")
- X || EQ(p, "OBJ")))
- X return(FALSE);
- X
- X /* Want .cshrc, .newsrc, etc.? */
- X if (*s == '.' && isalpha(s[1]))
- X return(DoDOTFILES);
- X
- X /* RCS or SCCS file or directory? */
- X if (EQ(s, "RCS")
- X || ((p = RDX(s, ',')) && *++p == 'v' && *++p == '\0')
- X || EQ(s, "SCCS") || (s[0] == 's' && s[1] == '.'))
- X return(DoRCS);
- X
- X /* Mlisp, m4 (yes to .m? but no to .mo)? */
- X /* really, no to .mo but yes to names matching the regexp ".m?" */
- X if ((p = d) && *++p == 'm' && p[2] == '\0')
- X return(*++p != 'o');
- X
- X /* Gnu Emacs elisp (yes to .el*, but no to .elc)? */
- X if ((p = d) && *++p == 'e' && *++p == 'l')
- X return(*++p != 'c' || *++p);
- X
- X /* C source (*.[ch])? */
- X if ((p = d) && (*++p == 'c' || *p == 'h') && *++p == '\0')
- X
- X /* Manpage (*.[1234567890] or *.man)? */
- X if ((p = d) && isdigit(*p))
- X return(TRUE);
- X if ((p = d) && *++p == 'm' && *++p == 'a' && *++p == 'n')
- X return(TRUE);
- X
- X /* Make control file? */
- X if ((*s == 'M' || *s == 'm') && EQ(s + 1, "akefile"))
- X return(TRUE);
- X
- X /* Convert to lowercase, and see if it's a README or MANIFEST. */
- X for (p = strcpy(buff, s); *p; p++)
- X if (isascii(*p) && isupper(*p))
- X *p = tolower(*p);
- X if (EQ(buff, "readme") || EQ(buff, "read_me") || EQ(buff, "read-me")
- X || EQ(buff, "manifest"))
- X return(TRUE);
- X
- X /* Larry Wall-style template file (*.SH)? */
- X if ((p = d) && *++p == 'S' && *++p == 'H')
- X return(TRUE);
- X
- X /* If we have a default, give it back. */
- X if (Default)
- X return(Default == 'y');
- X
- X#ifdef CAN_POPEN
- X /* See what file(1) has to say; if it says executable, punt. */
- X (void)sprintf(buff, "exec file '%s'", Name);
- X if (F = popen(buff, "r")) {
- X (void)fgets(buff, sizeof buff, F);
- X (void)pclose(F);
- X for (p = buff; p = IDX(p, 'e'); p++)
- X if (PREFIX(p, "executable"))
- X return(FALSE);
- X (void)fputs(buff, stderr);
- X }
- X#endif /* CAN_POPEN */
- X
- X /* Add it? */
- X while (TRUE) {
- X if (DEVTTY == NULL)
- X DEVTTY = fopen(THE_TTY, "r");
- X Fprintf(stderr, "Add this one (y or n)[y]? ");
- X (void)fflush(stderr);
- X if (fgets(buff, sizeof buff, DEVTTY) == NULL
- X || buff[0] == '\n' || buff[0] == 'y' || buff[0] == 'Y')
- X break;
- X if (buff[0] == 'n' || buff[0] == 'N')
- X return(FALSE);
- X if (buff[0] == '!' )
- X (void)system(&buff[1]);
- X Fprintf(stderr, "--------------------\n%s: ", Name);
- X clearerr(DEVTTY);
- X }
- X return(TRUE);
- X}
- X
- X
- X/*
- X** Quick and dirty recursive routine to walk down directory tree.
- X** Could be made more general, but why bother?
- X*/
- static void
- Process(p, level)
- X REGISTER char *p;
- X REGISTER int level;
- X{
- X REGISTER char *q;
- X DIR *Dp;
- X DIRENTRY *E;
- X char buff[BUFSIZ];
- X
- X#ifdef MSDOS
- X strlwr(p);
- X#endif /* MSDOS */
- X
- X if (!GetStat(p))
- X Fprintf(stderr, "Can't walk down %s, %s.\n", Ermsg(errno));
- X else {
- X /* Skip leading ./ which find(1), e.g., likes to put out. */
- X if (p[0] == '.' && p[1] == '/')
- X p += 2;
- X
- X if (Wanted(p))
- X Fprintf(Ftype(p) == F_FILE ? Ffile : Dfile, "%s\n", p);
- X else if (Verbose)
- X Fprintf(Ftype(p) == F_FILE ? Ffile : Dfile, "PUNTED %s\n", p);
- X
- X if (Ftype(p) == F_DIR)
- X if (++level == MAX_LEVELS)
- X Fprintf(stderr, "Won't walk down %s -- more than %d levels.\n",
- X p, level);
- X else if (Dp = opendir(p)) {
- X q = buff + strlen(strcpy(buff, p));
- X for (*q++ = '/'; E = readdir(Dp); )
- X if (!EQ(E->d_name, ".") && !EQ(E->d_name, "..")) {
- X (void)strcpy(q, E->d_name);
- X Process(buff, level);
- X }
- X (void)closedir(Dp);
- X }
- X else
- X Fprintf(stderr, "Can't open directory %s, %s.\n",
- X p, Ermsg(errno));
- X }
- X}
- X
- X
- main(ac, av)
- X REGISTER int ac;
- X REGISTER char *av[];
- X{
- X REGISTER char *p;
- X REGISTER int i;
- X REGISTER int Oops;
- X char buff[BUFSIZ];
- X
- X /* Parse JCL. */
- X for (Oops = 0; (i = getopt(ac, av, ".d:o:RSv")) != EOF; )
- X switch (i) {
- X default:
- X Oops++;
- X break;
- X case '.':
- X DoDOTFILES++;
- X break;
- X case 'd':
- X switch (optarg[0]) {
- X default:
- X Oops++;
- X break;
- X case 'y':
- X case 'Y':
- X Default = 'y';
- X break;
- X case 'n':
- X case 'N':
- X Default = 'n';
- X break;
- X }
- X break;
- X case 'o':
- X if (freopen(optarg, "w", stdout) == NULL) {
- X Fprintf(stderr, "Can't open %s for output, %s.\n",
- X optarg, Ermsg(errno));
- X exit(1);
- X }
- X case 'R':
- X case 'S':
- X DoRCS++;
- X break;
- X case 'v':
- X Verbose++;
- X break;
- X }
- X if (Oops) {
- X Fprintf(stderr, "Usage: findsrc [-d{yn}] [-.] [-{RS}] [-v] files...\n");
- X exit(1);
- X }
- X av += optind;
- X
- X /* Set signal catcher, open temp files. */
- X SetSigs(TRUE, Catch);
- X Dname = mktemp("/tmp/findDXXXXXX");
- X Fname = mktemp("/tmp/findFXXXXXX");
- X Dfile = fopen(Dname, "w");
- X Ffile = fopen(Fname, "w");
- X
- X /* Read list of files, determine their status. */
- X if (*av)
- X for (DEVTTY = stdin; *av; av++)
- X Process(*av, 0);
- X else
- X while (fgets(buff, sizeof buff, stdin)) {
- X if (p = IDX(buff, '\n'))
- X *p = '\0';
- X else
- X Fprintf(stderr, "Warning, line too long:\n\t%s\n", buff);
- X Process(buff, 0);
- X }
- X
- X /* First print directories. */
- X if (freopen(Dname, "r", Dfile)) {
- X while (fgets(buff, sizeof buff, Dfile))
- X (void)fputs(buff, stdout);
- X (void)fclose(Dfile);
- X }
- X
- X /* Now print regular files. */
- X if (freopen(Fname, "r", Ffile)) {
- X while (fgets(buff, sizeof buff, Ffile))
- X (void)fputs(buff, stdout);
- X (void)fclose(Ffile);
- X }
- X
- X /* That's all she wrote. */
- X (void)unlink(Dname);
- X (void)unlink(Fname);
- X exit(0);
- X}
- END_OF_FILE
- if test 7195 -ne `wc -c <'findsrc.c'`; then
- echo shar: \"'findsrc.c'\" unpacked with wrong size!
- fi
- # end of 'findsrc.c'
- fi
- if test -f 'makekit.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'makekit.c'\"
- else
- echo shar: Extracting \"'makekit.c'\" \(10488 characters\)
- sed "s/^X//" >'makekit.c' <<'END_OF_FILE'
- X/*
- X** MAKEKIT
- X** Split up source files into reasonably-sized shar lists.
- X*/
- X#include "shar.h"
- X#ifdef RCSID
- static char RCS[] =
- X "$Header: makekit.c,v 2.0 88/05/27 13:27:31 rsalz Exp $";
- X#endif /* RCSID */
- X
- X
- X/*
- X** Our block of information about the files we're doing.
- X*/
- typedef struct _block {
- X char *Name; /* Filename */
- X char *Text; /* What it is */
- X int Where; /* Where it is */
- X int Type; /* Directory or file? */
- X long Bsize; /* Size in bytes */
- X} BLOCK;
- X
- X
- X/*
- X** Our block of information about the archives we're making.
- X*/
- typedef struct _archive {
- X int Count; /* Number of files */
- X long Asize; /* Bytes used by archive */
- X} ARCHIVE;
- X
- X
- X/*
- X** Format strings; these are strict K&R so you shouldn't have to change them.
- X*/
- X#define FORMAT1 " %-25s %2d\t%s\n"
- X#define FORMAT2 "%s%2.2d"
- X#ifdef FMT02d
- X#undef FORMAT2
- X#define FORMAT2 "%s%02.2d" /* I spoke too soon... */
- X#endif /* FMT02d */
- X
- X
- X/*
- X** Global variables.
- X*/
- char *InName; /* File with list to pack */
- char *OutName; /* Where our output goes */
- char *SharName = "Part"; /* Prefix for name of each shar */
- char *Trailer; /* Text for shar to pack in */
- char *TEMP; /* Temporary manifest file */
- X#ifdef MSDOS
- char *FLST; /* File with list for shar */
- X#endif MSDOS
- int ArkCount = 20; /* Max number of archives */
- int ExcludeIt; /* Leave out the output file? */
- int Header; /* Lines of prolog in input */
- int Preserve; /* Preserve order for Manifest? */
- int Working = TRUE; /* Call shar when done? */
- long Size = 55000; /* Largest legal archive size */
- X
- X
- X/*
- X** Sorting predicate to put README or MANIFEST first, then directories,
- X** then larger files, then smaller files, which is how we want to pack
- X** stuff in archives.
- X*/
- static int
- SizeP(t1, t2)
- X BLOCK *t1;
- X BLOCK *t2;
- X{
- X long i;
- X
- X if (t1->Type == F_DIR)
- X return(t2->Type == F_DIR ? 0 : -1);
- X if (t2->Type == F_DIR)
- X return(1);
- X if (EQn(t1->Name, "README", 6) || (OutName && EQ(t1->Name, OutName)))
- X return(-1);
- X if (EQn(t2->Name, "README", 6) || (OutName && EQ(t2->Name, OutName)))
- X return(1);
- X return((i = t1->Bsize - t2->Bsize) == 0L ? 0 : (i < 0L ? -1 : 1));
- X}
- X
- X
- X/*
- X** Sorting predicate to get things in alphabetical order, which is how
- X** we write the Manifest file.
- X*/
- static int
- NameP(t1, t2)
- X BLOCK *t1;
- X BLOCK *t2;
- X{
- X int i;
- X
- X return((i = *t1->Name - *t2->Name) ? i : strcmp(t1->Name, t2->Name));
- X}
- X
- X
- X/*
- X** Skip whitespace.
- X*/
- static char *
- Skip(p)
- X REGISTER char *p;
- X{
- X while (*p && WHITE(*p))
- X p++;
- X return(p);
- X}
- X
- X
- X/*
- X** Signal handler. Clean up and die.
- X*/
- static sigret_t
- Catch(s)
- X int s;
- X{
- X int e;
- X
- X e = errno;
- X if (TEMP)
- X (void)unlink(TEMP);
- X#ifdef MSDOS
- X if (FLST)
- X (void)unlink(FLST);
- X#endif /* MSDOS */
- X Fprintf(stderr, "Got signal %d, %s.\n", s, Ermsg(e));
- X exit(1);
- X}
- X
- X
- main(ac, av)
- X REGISTER int ac;
- X char *av[];
- X{
- X REGISTER FILE *F;
- X REGISTER FILE *In;
- X REGISTER BLOCK *t;
- X REGISTER ARCHIVE *k;
- X REGISTER char *p;
- X REGISTER int i;
- X REGISTER int lines;
- X REGISTER int Value;
- X BLOCK *Table;
- X BLOCK *TabEnd;
- X ARCHIVE *Ark;
- X ARCHIVE *ArkEnd;
- X char buff[BUFSIZ];
- X long lsize;
- X int LastOne;
- X int Start;
- X int Notkits;
- X char EndArkNum[20];
- X char CurArkNum[20];
- X
- X /* Collect input. */
- X Value = FALSE;
- X Notkits = FALSE;
- X while ((i = getopt(ac, av, "1eh:i:k:n:mo:p:s:t:x")) != EOF)
- X switch (i) {
- X default:
- X Fprintf(stderr,
- X"usage: makekit -e -s# [-m | -iMANIFEST -oMANIFEST -h2] -nName -tText files..."
- X );
- X exit(1);
- X case '1':
- X Notkits = TRUE;
- X break;
- X case 'e':
- X ExcludeIt = TRUE;
- X break;
- X case 'h':
- X Header = atoi(optarg);
- X break;
- X case 'i':
- X InName = optarg;
- X break;
- X case 'k':
- X ArkCount = atoi(optarg);
- X break;
- X case 'm':
- X InName = OutName = "MANIFEST";
- X Header = 2;
- X break;
- X case 'n':
- X SharName = optarg;
- X break;
- X case 'o':
- X OutName = optarg;
- X break;
- X case 'p':
- X Preserve = TRUE;
- X break;
- X case 's':
- X Size = atoi(optarg);
- X if (IDX(optarg, 'k') || IDX(optarg, 'K'))
- X Size *= 1024;
- X break;
- X case 't':
- X Trailer = optarg;
- X break;
- X case 'x':
- X Working = FALSE;
- X break;
- X }
- X ac -= optind;
- X av += optind;
- X
- X /* Write the file list to a temp file. */
- X TEMP = mktemp("/tmp/maniXXXXXX");
- X F = fopen(TEMP, "w");
- X SetSigs(TRUE, Catch);
- X if (av[0])
- X /* Got the arguments on the command line. */
- X while (*av)
- X Fprintf(F, "%s\n", *av++);
- X else {
- X /* Got the name of the file from the command line. */
- X if (InName == NULL)
- X In = stdin;
- X else if ((In = fopen(InName, "r")) == NULL) {
- X Fprintf(stderr, "Can't read %s as manifest, %s.\n",
- X InName, Ermsg(errno));
- X exit(1);
- X }
- X /* Skip any possible prolog, then output rest of file. */
- X while (--Header >= 0 && fgets(buff, sizeof buff, In))
- X ;
- X if (feof(In)) {
- X Fprintf(stderr, "Nothing but header lines in list!?\n");
- X exit(1);
- X }
- X while (fgets(buff, sizeof buff, In))
- X fputs(buff, F);
- X if (In != stdin)
- X (void)fclose(In);
- X }
- X (void)fclose(F);
- X
- X /* Count number of files, allow for NULL and our output file. */
- X F = fopen(TEMP, "r");
- X for (lines = 2; fgets(buff, sizeof buff, F); lines++)
- X ;
- X rewind(F);
- X
- X /* Read lines and parse lines, see if we found our OutFile. */
- X Table = NEW(BLOCK, lines);
- X for (t = Table, Value = FALSE, lines = 0; fgets(buff, sizeof buff, F); ) {
- X /* Read line, skip first word, check for blank line. */
- X if (p = IDX(buff, '\n'))
- X *p = '\0';
- X else
- X Fprintf(stderr, "Warning, line truncated:\n%s\n", buff);
- X p = Skip(buff);
- X if (*p == '\0')
- X continue;
- X
- X /* Copy the line, snip off the first word. */
- X for (p = t->Name = COPY(p); *p && !WHITE(*p); p++)
- X ;
- X if (*p)
- X *p++ = '\0';
- X
- X /* Skip <spaces><digits><spaces>; remainder is the file description. */
- X for (p = Skip(p); *p && isdigit(*p); )
- X p++;
- X t->Text = Skip(p);
- X
- X /* Get file type. */
- X if (!GetStat(t->Name)) {
- X Fprintf(stderr, "Can't stat %s (%s), skipping.\n",
- X t->Name, Ermsg(errno));
- X continue;
- X }
- X t->Type = Ftype(t->Name);
- X
- X /* Guesstimate its size when archived: prolog, plus one char/line. */
- X t->Bsize = strlen(t->Name) * 3 + 200;
- X if (t->Type == F_FILE) {
- X lsize = Fsize(t->Name);
- X t->Bsize += lsize + lsize / 60;
- X }
- X if (t->Bsize > Size) {
- X Fprintf(stderr, "At %ld bytes, %s is too big for any archive!\n",
- X t->Bsize, t->Name);
- X exit(1);
- X }
- X
- X /* Is our ouput file there? */
- X if (!Value && OutName && EQ(OutName, t->Name))
- X Value = TRUE;
- X
- X /* All done -- advance to next entry. */
- X t++;
- X }
- X (void)fclose(F);
- X (void)unlink(TEMP);
- X SetSigs(S_RESET, (sigret_t (*)())NULL);
- X
- X /* Add our output file? */
- X if (!ExcludeIt && !Value && OutName) {
- X t->Name = OutName;
- X t->Text = "This shipping list";
- X t->Type = F_FILE;
- X t->Bsize = lines * 60;
- X t++;
- X }
- X
- X /* Sort by size, get archive space. */
- X lines = t - Table;
- X TabEnd = &Table[lines];
- X if (!Preserve)
- X qsort((char *)Table, lines, sizeof Table[0], SizeP);
- X Ark = NEW(ARCHIVE, ArkCount);
- X ArkEnd = &Ark[ArkCount];
- X
- X /* Loop through the pieces, and put everyone into an archive. */
- X for (t = Table; t < TabEnd; t++) {
- X for (k = Ark; k < ArkEnd; k++)
- X if (t->Bsize + k->Asize < Size) {
- X k->Asize += t->Bsize;
- X t->Where = k - Ark;
- X k->Count++;
- X break;
- X }
- X if (k == ArkEnd) {
- X Fprintf(stderr, "'%s' doesn't fit -- need more then %d archives.\n",
- X t->Name, ArkCount);
- X exit(1);
- X }
- X /* Since our share doesn't build sub-directories... */
- X if (t->Type == F_DIR && k != Ark)
- X Fprintf(stderr, "Warning: directory '%s' is in archive %d\n",
- X t->Name, k - Ark + 1);
- X }
- X
- X /* Open the output file. */
- X if (OutName == NULL)
- X F = stdout;
- X else {
- X if (GetStat(OutName)) {
- X /* Handle /foo/bar/VeryLongFileName.BAK for non-BSD sites. */
- X (void)sprintf(buff, "%s.BAK", OutName);
- X p = (p = RDX(buff, '/')) ? p + 1 : buff;
- X if (strlen(p) > 14)
- X /* ... well, sort of handle it. */
- X (void)strcpy(&p[10], ".BAK");
- X Fprintf(stderr, "Renaming %s to %s\n", OutName, buff);
- X (void)unlink(buff);
- X (void)link(OutName, buff);
- X (void)unlink(OutName);
- X }
- X if ((F = fopen(OutName, "w")) == NULL) {
- X Fprintf(stderr, "Can't open '%s' for output, %s.\n",
- X OutName, Ermsg(errno));
- X exit(1);
- X }
- X }
- X
- X /* Sort the shipping list, then write it. */
- X if (!Preserve)
- X qsort((char *)Table, lines, sizeof Table[0], NameP);
- X Fprintf(F, " File Name\t\tArchive #\tDescription\n");
- X Fprintf(F, "-----------------------------------------------------------\n");
- X for (t = Table; t < TabEnd; t++)
- X Fprintf(F, FORMAT1, t->Name, t->Where + 1, t->Text);
- X
- X /* Close output. Are we done? */
- X if (F != stdout)
- X (void)fclose(F);
- X if (!Working)
- X exit(0);
- X
- X /* Find last archive number. */
- X for (i = 0, t = Table; t < TabEnd; t++)
- X if (i < t->Where)
- X i = t->Where;
- X LastOne = i + 1;
- X
- X /* Find archive with most files in it. */
- X for (i = 0, k = Ark; k < ArkEnd; k++)
- X if (i < k->Count)
- X i = k->Count;
- X
- X /* Build the fixed part of the argument vector. */
- X av = NEW(char*, i + 10);
- X av[0] = "shar";
- X i = 1;
- X if (Trailer) {
- X av[i++] = "-t";
- X av[i++] = Trailer;
- X }
- X if (Notkits == FALSE) {
- X (void)sprintf(EndArkNum, "%d", LastOne);
- X av[i++] = "-e";
- X av[i++] = EndArkNum;
- X av[i++] = "-n";
- X av[i++] = CurArkNum;
- X }
- X#ifdef MSDOS
- X av[i++] = "-i";
- X av[i++] = FLST = mktemp("/tmp/manlXXXXXX");
- X#endif /* MSDOS */
- X
- X av[i++] = "-o";
- X av[i++] = buff;
- X
- X /* Call shar to package up each archive. */
- X for (Start = i, i = 0; i < LastOne; i++) {
- X (void)sprintf(CurArkNum, "%d", i + 1);
- X (void)sprintf(buff, FORMAT2, SharName, i + 1);
- X#ifndef MSDOS
- X for (lines = Start, t = Table; t < TabEnd; t++)
- X if (t->Where == i)
- X av[lines++] = t->Name;
- X av[lines] = NULL;
- X#else
- X if ((F = fopen(FLST, "w")) == NULL) {
- X Fprintf(stderr, "Can't open list file '%s' for output, %s.\n",
- X FLST, Ermsg(errno));
- X exit(1);
- X }
- X for (t = Table; t < TabEnd; t++)
- X if (t->Where == i)
- X Fprintf(F, "%s\n", t->Name);
- X (void)fclose(F);
- X#endif /* MSDOS */
- X Fprintf(stderr, "Packing kit %d...\n", i + 1);
- X if (lines = Execute(av))
- X Fprintf(stderr, "Warning: shar returned status %d.\n", lines);
- X }
- X
- X#ifdef MSDOS
- X (void)unlink(FLST);
- X#endif /* MSDOS */
- X /* That's all she wrote. */
- X exit(0);
- X}
- END_OF_FILE
- if test 10488 -ne `wc -c <'makekit.c'`; then
- echo shar: \"'makekit.c'\" unpacked with wrong size!
- fi
- # end of 'makekit.c'
- fi
- if test -f 'shar.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'shar.c'\"
- else
- echo shar: Extracting \"'shar.c'\" \(7551 characters\)
- sed "s/^X//" >'shar.c' <<'END_OF_FILE'
- X/*
- X** SHAR
- X** Make a shell archive of a list of files.
- X*/
- X#include "shar.h"
- X#ifdef RCSID
- static char RCS[] =
- X "$Header: shar.c,v 2.0 88/05/27 14:10:47 rsalz Exp $";
- X#endif /* RCSID */
- X
- X/*
- X** Minimum allocation of file name pointers used in "-i" option processing.
- X*/
- X#define MIN_FILES 50
- X
- X
- X/*
- X** This prolog is output before the archive.
- X*/
- static char *Prolog[] = {
- X "! /bin/sh",
- X " This is a shell archive. Remove anything before this line, then unpack",
- X " it by saving it into a file and typing \"sh file\". To overwrite existing",
- X " files, type \"sh file -c\". You can also feed this as standard input via",
- X " unshar, or by typing \"sh <file\", e.g.. If this archive is complete, you",
- X " will see the following message at the end:",
- X NULL
- X};
- X
- X
- X/*
- X** Package up one file or directory.
- X*/
- static void
- shar(file, Basename)
- X char *file;
- X int Basename;
- X{
- X REGISTER char *s;
- X REGISTER char *Name;
- X REGISTER int Bads;
- X REGISTER off_t Size;
- X char buf[BUFSIZ];
- X
- X /* Just in case. */
- X if (EQ(file, ".") || EQ(file, ".."))
- X return;
- X
- X Size = Fsize(file);
- X Name = Basename && (Name = RDX(file, '/')) ? Name + 1 : file;
- X
- X /* Making a directory? */
- X if (Ftype(file) == F_DIR) {
- X Printf("if test ! -d '%s' ; then\n", Name);
- X Printf(" echo shar: Creating directory \\\"'%s'\\\"\n", Name);
- X Printf(" mkdir '%s'\n", Name);
- X Printf("fi\n");
- X }
- X else {
- X if (freopen(file, "r", stdin) == NULL) {
- X Fprintf(stderr, "Can't open %s, %s\n", file, Ermsg(errno));
- X exit(1);
- X }
- X
- X /* Emit the per-file prolog. */
- X Printf("if test -f '%s' -a \"${1}\" != \"-c\" ; then \n", Name);
- X Printf(" echo shar: Will not clobber existing file \\\"'%s'\\\"\n",
- X Name);
- X Printf("else\n");
- X Printf("echo shar: Extracting \\\"'%s'\\\" \\(%ld character%s\\)\n",
- X Name, (long)Size, Size == 1 ? "" : "s");
- X Printf("sed \"s/^X//\" >'%s' <<'END_OF_FILE'\n", Name, Name);
- X
- X /* Output the file contents. */
- X for (Bads = 0; fgets(buf, BUFSIZ, stdin); )
- X if (buf[0]) {
- X if (buf[0] == 'X' || buf[0] == 'E' || buf[0] == 'F'
- X || !isalpha(buf[0]))
- X /* Protect non-alpha's, the shar pattern character, the
- X * END_OF_FILE message, and mail "From" lines. */
- X (void)putchar('X');
- X for (s = buf; *s; s++) {
- X if (BADCHAR(*s))
- X Bads++;
- X (void)putchar(*s);
- X }
- X }
- X
- X /* Tell about and control characters. */
- X Printf("END_OF_FILE\n", Name);
- X if (Bads) {
- X Printf(
- X "echo shar: %d control character%s may be missing from \\\"'%s'\\\"\n",
- X Bads, Bads == 1 ? "" : "s", Name);
- X Fprintf(stderr, "Found %d control char%s in \"'%s'\"\n",
- X Bads, Bads == 1 ? "" : "s", Name);
- X }
- X
- X /* Output size check. */
- X Printf("if test %ld -ne `wc -c <'%s'`; then\n", (long)Size, Name);
- X Printf(" echo shar: \\\"'%s'\\\" unpacked with wrong size!\n", Name);
- X Printf("fi\n");
- X
- X /* Executable? */
- X if (Fexecute(file))
- X Printf("chmod +x '%s'\n", Name);
- X
- X Printf("# end of '%s'\nfi\n", Name);
- X }
- X}
- X
- X
- X/*
- X** Read list of files from file.
- X*/
- static char **
- GetFiles(Name)
- X char *Name;
- X{
- X REGISTER FILE *F;
- X REGISTER int i;
- X REGISTER int count;
- X REGISTER char **files;
- X REGISTER char **temp;
- X REGISTER int j;
- X char buff[BUFSIZ];
- X char *p;
- X
- X /* Open the file. */
- X if (EQ(Name, "-"))
- X F = stdin;
- X else if ((F = fopen(Name, "r")) == NULL) {
- X Fprintf(stderr, "Can't open '%s' for input.\n", Name);
- X return(NULL);
- X }
- X
- X /* Get space. */
- X count = MIN_FILES;
- X files = NEW(char*, count);
- X
- X /* Read lines. */
- X for (i = 0; fgets(buff, sizeof buff, F); ) {
- X if (p = IDX(buff, '\n'))
- X *p = '\0';
- X files[i] = COPY(buff);
- X if (++i == count - 2) {
- X /* Get more space; some systems don't have realloc()... */
- X for (count += MIN_FILES, temp = NEW(char*, count), j = 0; j < i; j++)
- X temp[j] = files[j];
- X files = temp;
- X }
- X }
- X
- X /* Clean up, close up, return. */
- X files[i] = NULL;
- X (void)fclose(F);
- X return(files);
- X}
- X
- X
- X
- main(ac, av)
- X int ac;
- X REGISTER char *av[];
- X{
- X REGISTER char *Trailer;
- X REGISTER char *p;
- X REGISTER char *q;
- X REGISTER int i;
- X REGISTER int length;
- X REGISTER int Oops;
- X REGISTER int Knum;
- X REGISTER int Kmax;
- X REGISTER int Basename;
- X REGISTER int j;
- X time_t clock;
- X char **Flist;
- X
- X /* Parse JCL. */
- X Basename = 0;
- X Knum = 0;
- X Kmax = 0;
- X Trailer = NULL;
- X for (Oops = 0; (i = getopt(ac, av, "be:i:n:o:t:")) != EOF; )
- X switch (i) {
- X default:
- X Oops++;
- X break;
- X case 'b':
- X Basename++;
- X break;
- X case 'e':
- X Kmax = atoi(optarg);
- X break;
- X case 'i':
- X Flist = GetFiles(optarg);
- X break;
- X case 'n':
- X Knum = atoi(optarg);
- X break;
- X case 'o':
- X if (freopen(optarg, "w", stdout) == NULL) {
- X Fprintf(stderr, "Can't open %s for output, %s.\n",
- X optarg, Ermsg(errno));
- X Oops++;
- X }
- X break;
- X case 't':
- X Trailer = optarg;
- X break;
- X }
- X
- X /* Rest of arguments are files. */
- X if (Flist == NULL) {
- X av += optind;
- X if (*av == NULL) {
- X Fprintf(stderr, "No input files\n");
- X Oops++;
- X }
- X Flist = av;
- X }
- X
- X if (Oops) {
- X Fprintf(stderr,
- X "USAGE: shar [-b] [-o:] [-i:] [-n:e:t:] file... >SHAR\n");
- X exit(1);
- X }
- X
- X /* Everything readable and reasonably-named? */
- X for (Oops = 0, i = 0; p = Flist[i]; i++)
- X if (freopen(p, "r", stdin) == NULL) {
- X Fprintf(stderr, "Can't read %s, %s.\n", p, Ermsg(errno));
- X Oops++;
- X }
- X else
- X for (; *p; p++)
- X if (!isascii(*p)) {
- X Fprintf(stderr, "Bad character '%c' in '%s'.\n",
- X *p, Flist[i]);
- X Oops++;
- X }
- X if (Oops)
- X exit(2);
- X
- X /* Prolog. */
- X for (i = 0; p = Prolog[i]; i++)
- X Printf("#%s\n", p);
- X if (Knum && Kmax)
- X Printf("#\t\t\"End of archive %d (of %d).\"\n", Knum, Kmax);
- X else
- X Printf("#\t\t\"End of shell archive.\"\n");
- X Printf("# Contents: ");
- X for (length = 12, i = 0; p = Flist[i++]; length += j) {
- X if (Basename && (q = RDX(p, '/')))
- X p = q + 1;
- X j = strlen(p) + 1;
- X if (length + j < WIDTH)
- X Printf(" %s", p);
- X else {
- X Printf("\n# %s", p);
- X length = 4;
- X }
- X }
- X Printf("\n");
- X clock = time((time_t *)NULL);
- X Printf("# Wrapped by %s@%s on %s", User(), Host(), ctime(&clock));
- X Printf("PATH=/bin:/usr/bin:/usr/ucb ; export PATH\n");
- X
- X /* Do it. */
- X while (*Flist)
- X shar(*Flist++, Basename);
- X
- X /* Epilog. */
- X if (Knum && Kmax) {
- X Printf("echo shar: End of archive %d \\(of %d\\).\n", Knum, Kmax);
- X Printf("cp /dev/null ark%disdone\n", Knum);
- X Printf("MISSING=\"\"\n");
- X Printf("for I in");
- X for (i = 0; i < Kmax; i++)
- X Printf(" %d", i + 1);
- X Printf(" ; do\n");
- X Printf(" if test ! -f ark${I}isdone ; then\n");
- X Printf("\tMISSING=\"${MISSING} ${I}\"\n");
- X Printf(" fi\n");
- X Printf("done\n");
- X Printf("if test \"${MISSING}\" = \"\" ; then\n");
- X if (Kmax == 1)
- X Printf(" echo You have the archive.\n");
- X else if (Kmax == 2)
- X Printf(" echo You have unpacked both archives.\n");
- X else
- X Printf(" echo You have unpacked all %d archives.\n", Kmax);
- X if (Trailer && *Trailer)
- X Printf(" echo \"%s\"\n", Trailer);
- X Printf(" rm -f ark[1-9]isdone%s\n",
- X Kmax >= 9 ? " ark[1-9][0-9]isdone" : "");
- X Printf("else\n");
- X Printf(" echo You still need to unpack the following archives:\n");
- X Printf(" echo \" \" ${MISSING}\n");
- X Printf("fi\n");
- X Printf("## End of shell archive.\n");
- X }
- X else {
- X Printf("echo shar: End of shell archive.\n");
- X if (Trailer && *Trailer)
- X Printf("echo \"%s\"\n", Trailer);
- X }
- X
- X Printf("exit 0\n");
- X
- X exit(0);
- X}
- END_OF_FILE
- if test 7551 -ne `wc -c <'shar.c'`; then
- echo shar: \"'shar.c'\" unpacked with wrong size!
- fi
- # end of 'shar.c'
- fi
- if test -f 'unshar.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'unshar.c'\"
- else
- echo shar: Extracting \"'unshar.c'\" \(8368 characters\)
- sed "s/^X//" >'unshar.c' <<'END_OF_FILE'
- X/*
- X** UNSHAR
- X** Unpack shell archives that might have gone through mail, notes, news, etc.
- X** This is Michael Mauldin's code which I have usurped and heavily modified.
- X*/
- X#include "shar.h"
- X#ifdef RCSID
- static char RCS[] =
- X "$Header: unshar.c,v 2.0 88/05/27 13:28:13 rsalz Exp $";
- X#endif /* RCSID */
- X
- X
- X/*
- X** Print error message and die.
- X*/
- static void
- Quit(text)
- X char *text;
- X{
- X int e;
- X
- X e = errno;
- X Fprintf(stderr, "unshar: %s", text);
- X if (e)
- X Fprintf(stderr, ", %s", Ermsg(e));
- X Fprintf(stderr, ".\n");
- X exit(1);
- X}
- X
- X
- X/*
- X** Does this look like a mail header line?
- X*/
- static int
- IsHeader(p)
- X REGISTER char *p;
- X{
- X REGISTER int i;
- X
- X if (*p == '\0' || *p == '\n')
- X return(FALSE);
- X if (WHITE(*p))
- X return(TRUE);
- X for (i = 0; *p == '-' || *p == '_' || *p == '.' || isalnum(*p); i++)
- X p++;
- X return(i && *p == ':');
- X}
- X
- X
- X/*
- X** Is this a /bin/sh comment line? We check that because some shars
- X** output comments before the CUT line.
- X*/
- static int
- IsSHcomment(p)
- X REGISTER char *p;
- X{
- X while (isalpha(*p) || WHITE(*p) || *p == '\n' || *p == ',' || *p == '.')
- X p++;
- X return(*p == '\0');
- X}
- X
- X
- X/*
- X** Return TRUE if p has wd1 and wd2 as words (i.e., no preceeding or
- X** following letters). Clever code, Michael.
- X*/
- static int
- Has(p, wd1, wd2)
- X REGISTER char *p;
- X REGISTER char *wd1;
- X REGISTER char *wd2;
- X{
- X REGISTER char *wd;
- X REGISTER int first;
- X
- X wd = wd1;
- X first = TRUE;
- again:
- X while (*p) {
- X if (!isalpha(*p)) {
- X p++;
- X continue;
- X }
- X while (*p++ == *wd++) {
- X if (*wd == '\0') {
- X if (!isalpha(*p)) {
- X if (!first)
- X return(TRUE);
- X first = FALSE;
- X wd = wd2;
- X goto again;
- X }
- X break;
- X }
- X }
- X while (isalpha(*p))
- X p++;
- X wd = first ? wd1 : wd2;
- X }
- X return(FALSE);
- X}
- X
- X
- X/*
- X** Here's where the work gets done. Skip headers and try to intuit
- X** if the file is, e.g., C code, etc.
- X*/
- static int
- XFound(Name, buff, Forced, Stream, Header)
- X REGISTER char *Name;
- X REGISTER char *buff;
- X REGISTER int Forced;
- X REGISTER FILE *Stream;
- X REGISTER FILE *Header;
- X{
- X REGISTER char *p;
- X REGISTER int InHeader;
- X char lower[BUFSIZ];
- X
- X if (Header)
- X InHeader = TRUE;
- X
- X while (TRUE) {
- X /* Read next line, fail if no more */
- X if (fgets(buff, BUFSIZ, Stream) == NULL) {
- X Fprintf(stderr, "unshar: No shell commands in %s.\n", Name);
- X return(FALSE);
- X }
- X
- X /* See if it looks like another language. */
- X if (!Forced) {
- X if (PREFIX(buff, "#include") || PREFIX(buff, "# include")
- X || PREFIX(buff, "#define") || PREFIX(buff, "# define")
- X || PREFIX(buff, "#ifdef") || PREFIX(buff, "# ifdef")
- X || PREFIX(buff, "#ifndef") || PREFIX(buff, "# ifndef")
- X || (PREFIX(buff, "/*")
- X && !PREFIX(buff, NOTES1) && !PREFIX(buff, NOTES2)))
- X p = "C code";
- X else if (PREFIX(buff, "(*")) /* For vi :-) */
- X p = "PASCAL code";
- X else if (buff[0] == '.' && isalpha(buff[1]) && isalpha(buff[2])
- X && !isalpha(buff[3]))
- X p = "TROFF source";
- X else
- X p = NULL;
- X if (p) {
- X Fprintf(stderr,
- X "unshar: %s is apparently %s, not a shell archive.\n",
- X Name, p);
- X return(FALSE);
- X }
- X }
- X
- X /* Does this line start with a shell command or comment? */
- X if ((buff[0] == '#' && !IsSHcomment(buff + 1))
- X || buff[0] == ':' || PREFIX(buff, "echo ")
- X || PREFIX(buff, "sed ") || PREFIX(buff, "cat ")) {
- X return(TRUE);
- X }
- X
- X /* Does this line say "Cut here"? */
- X for (p = strcpy(lower, buff); *p; p++)
- X if (isascii(*p) && islower(*p))
- X *p = toupper(*p);
- X if (PREFIX(buff, "-----") || Has(lower, "cut", "here")
- X || Has(lower, "cut", "cut") || Has(lower, "tear", "here")) {
- X /* Get next non-blank line. */
- X do {
- X if (fgets(buff, BUFSIZ, Stream) == NULL) {
- X Fprintf(stderr, "unshar: cut line is last line of %s\n",
- X Name);
- X return(FALSE);
- X }
- X } while (*buff == '\n');
- X
- X /* If it starts with a comment or lower-case letter we win. */
- X if (*buff == '#' || *buff == ':' || islower(*buff))
- X return(TRUE);
- X
- X /* The cut message lied. */
- X Fprintf(stderr, "unshar: %s is not a shell archive,\n", Name);
- X Fprintf(stderr, " the 'cut' line was followed by: %s", buff);
- X return(FALSE);
- X }
- X
- X if (Header) {
- X (void)fputs(buff, Header);
- X if (InHeader && !IsHeader(buff))
- X InHeader = FALSE;
- X }
- X }
- X}
- X
- X
- X/*
- X** Create file for the header, find true start of the archive,
- X** and send it off to the shell.
- X*/
- static void
- Unshar(Name, HdrFile, Stream, Saveit, Forced)
- X char *Name;
- X char *HdrFile;
- X REGISTER FILE *Stream;
- X int Saveit;
- X int Forced;
- X{
- X REGISTER FILE *Header;
- X#ifndef USE_MY_SHELL
- X REGISTER FILE *Pipe;
- X#endif /* USE_MY_SHELL */
- X char *p;
- X char buff[BUFSIZ];
- X
- X if (Saveit) {
- X /* Create a name for the saved header. */
- X if (HdrFile)
- X (void)strcpy(buff, HdrFile);
- X else if (Name) {
- X p = RDX(Name, '/');
- X (void)strncpy(buff, p ? p + 1 : Name, 14);
- X buff[10] = 0;
- X (void)strcat(buff, ".hdr");
- X }
- X else
- X (void)strcpy(buff, "UNSHAR.HDR");
- X
- X /* Tell user, and open the file. */
- X Fprintf(stderr, "unshar: Sending header to %s.\n", buff);
- X if ((Header = fopen(buff, "a")) == NULL)
- X Quit("Can't open file for header");
- X }
- X else
- X Header = NULL;
- X
- X /* If name is NULL, we're being piped into... */
- X p = Name ? Name : "the standard input";
- X Printf("unshar: Doing %s:\n", p);
- X
- X if (Found(p, buff, Forced, Stream, Header)) {
- X#ifdef USE_MY_SHELL
- X BinSh(Name, Stream, buff);
- X#else
- X if ((Pipe = popen("/bin/sh", "w")) == NULL)
- X Quit("Can't open pipe to /bin/sh process");
- X
- X (void)fputs(buff, Pipe);
- X while (fgets(buff, sizeof buff, Stream))
- X (void)fputs(buff, Pipe);
- X
- X (void)pclose(Pipe);
- X#endif /* USE_MY_SHELL */
- X }
- X
- X /* Close the headers. */
- X if (Saveit)
- X (void)fclose(Header);
- X}
- X
- X
- main(ac, av)
- X REGISTER int ac;
- X REGISTER char *av[];
- X{
- X REGISTER FILE *Stream;
- X REGISTER int i;
- X char *p;
- X char *HdrFile;
- X char cwd[BUFSIZ];
- X char dir[BUFSIZ];
- X char buff[BUFSIZ];
- X int Saveit;
- X int Forced;
- X
- X /* Parse JCL. */
- X p = getenv("UNSHARDIR");
- X Saveit = DEF_SAVEIT;
- X HdrFile = NULL;
- X for (Forced = 0; (i = getopt(ac, av, "c:d:fh:ns")) != EOF; )
- X switch (i) {
- X default:
- X Quit("Usage: unshar [-fs] [-c dir] [-h hdrfile] [input files]");
- X /* NOTREACHED */
- X case 'c':
- X case 'd':
- X p = optarg;
- X break;
- X case 'f':
- X Forced++;
- X break;
- X case 'h':
- X HdrFile = optarg;
- X /* FALLTHROUGH */
- X case 's':
- X Saveit = TRUE;
- X break;
- X case 'n':
- X Saveit = FALSE;
- X break;
- X }
- X av += optind;
- X
- X /* Going somewhere? */
- X if (p) {
- X if (*p == '?') {
- X /* Ask for name; go to THE_TTY if we're being piped into. */
- X Stream = isatty(fileno(stdin)) ? stdin : fopen(THE_TTY, "r");
- X if (Stream == NULL)
- X Quit("Can't open tty to ask for directory");
- X Printf("unshar: what directory? ");
- X (void)fflush(stdout);
- X if (fgets(buff, sizeof buff, Stream) == NULL
- X || buff[0] == '\n'
- X || (p = IDX(buff, '\n')) == NULL)
- X Quit("Okay, cancelled");
- X *p = '\0';
- X p = buff;
- X if (Stream != stdin)
- X (void)fclose(Stream);
- X }
- X
- X /* If name is ~/blah, he means $HOME/blah. */
- X if (*p == '~') {
- X if (getenv("HOME") == NULL)
- X Quit("You have no $HOME?");
- X (void)sprintf(dir, "%s/%s", getenv("HOME"), p + 1);
- X p = dir;
- X }
- X
- X /* If we're gonna move, first remember where we were. */
- X if (Cwd(cwd, sizeof cwd) == NULL) {
- X Fprintf(stderr, "unshar warning: Can't get current directory.\n");
- X cwd[0] = '\0';
- X }
- X
- X /* Got directory; try to go there. Only make last component. */
- X if (chdir(p) < 0 && mkdir(p, 0777) < 0 && chdir(p) < 0)
- X Quit("Cannot chdir nor mkdir desired directory");
- X }
- X else
- X cwd[0] = '\0';
- X
- X /* No buffering. */
- X (void)setbuf(stdout, (char *)NULL);
- X (void)setbuf(stderr, (char *)NULL);
- X
- X if (*av)
- X /* Process filenames from command line. */
- X for (; *av; av++) {
- X if (cwd[0] && av[0][0] != '/') {
- X (void)sprintf(buff, "%s/%s", cwd, *av);
- X *av = buff;
- X }
- X if ((Stream = fopen(*av, "r")) == NULL)
- X Fprintf(stderr, "unshar: Can't open file '%s'.\n", *av);
- X else {
- X Unshar(*av, HdrFile, Stream, Saveit, Forced);
- X (void)fclose(Stream);
- X }
- X }
- X else
- X /* Do standard input. */
- X Unshar((char *)NULL, HdrFile, stdin, Saveit, Forced);
- X
- X /* That's all she wrote. */
- X exit(0);
- X}
- END_OF_FILE
- if test 8368 -ne `wc -c <'unshar.c'`; then
- echo shar: \"'unshar.c'\" unpacked with wrong size!
- fi
- # end of 'unshar.c'
- fi
- echo shar: End of archive 2 \(of 3\).
- cp /dev/null ark2isdone
- MISSING=""
- for I in 1 2 3 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 3 archives.
- echo "See the README"
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-